﻿using Crap4Net;
using NUnit.Framework;

namespace Crap4Net.UnitTests
{
    [TestFixture]
    public class MethodMatcherTest
    {
        static MethodSignature Method1 = new MethodSignature("Assembly", "nameSpace", "class1", "method", new string[] { });
        static MethodSignature Method2 = new MethodSignature("Assembly", "nameSpace", "class1", "method2", new string[] { });
        static MethodSignature Method1_UnknownAssembly = new MethodSignature("unknown", "nameSpace", "class1", "method", new string[] { });
        static MethodSignature Method1_WithDllExtension = new MethodSignature("Assembly.dll", "nameSpace", "class1", "method", new string[] { });

        [Test]
        public void IsMatching_SameMethod_ReturnTrue()
        {
            var actual = MethodMatcher.IsMatching(Method1, Method1);
            Assert.IsTrue(actual);
        }


        [Test]
        public void IsMatching_DifferentMethodNames_ReturnsFalse()
        {
            var actual = MethodMatcher.IsMatching(Method1, Method2);
            Assert.IsFalse(actual);
        }

        [Test]
        public void IsMatching_DifferentAssembliesNames_ReturnsFalse()
        {
            var method2 = new MethodSignature("otherdll", "nameSpace", "class1", "method", new string[] { });

            var actual = MethodMatcher.IsMatching(Method1, method2);
            Assert.IsFalse(actual);
        }

        [Test]
        public void IsMatching_DifferentNameSpaces_ReturnsFalse()
        {
            var method2 = new MethodSignature("dll", "OtherNameSpace", "class1", "method", new string[] { });

            var actual = MethodMatcher.IsMatching(Method1, method2);
            Assert.IsFalse(actual);
        }

        [Test]
        public void IsMatching_DifferentType_ReturnsFalse()
        {
            var method2 = new MethodSignature("dll", "nameSpace", "class2", "method", new string[] { });

            var actual = MethodMatcher.IsMatching(Method1, method2);
            Assert.IsFalse(actual);
        }

        [Test]
        public void IsMatching_DifferentArgumentNumber_ReturnsFalse()
        {
            var method2 = new MethodSignature("dll", "nameSpace", "class1", "method", new string[] { "int" });

            var actual = MethodMatcher.IsMatching(Method1, method2);
            Assert.IsFalse(actual);
        }

        [Test]
        public void IsMatching_DifferentArgs_ReturnsFalse()
        {
            var method1 = new MethodSignature("dll", "nameSpace", "class1", "method", new string[] { "int" });
            var method2 = new MethodSignature("dll", "nameSpace", "class1", "method", new string[] { "string" });

            var actual = MethodMatcher.IsMatching(method1, method2);
            Assert.IsFalse(actual);
        }



        [Test]
        public void IsMatching_AssmeblyWithDllExtensionAndWithoutDllExtension_dllExtensionIsIgnored()
        {

            var actual = MethodMatcher.IsMatching(Method1, Method1_WithDllExtension);
            Assert.IsTrue(actual);
        }
        
        [Test]
        public void IsMatching_UnknownAssemblyRestIsTheSame_ReturnsTrue()
        {
            var actual = MethodMatcher.IsMatching(Method1, Method1_UnknownAssembly);
            Assert.IsTrue(actual);
        }


        [Test]
        public void IsMatching_GenericMethodWithDifferentParamName_ReturnsTrue()
        {
            var method1 = new MethodSignature("dll", "dummyProject", "Class1", "method2<T>", new string[] { });
            var method2 = new MethodSignature("dll", "dummyProject", "Class1", "method2<1>", new string[] { });

            var actual = MethodMatcher.IsMatching(method1, method2);
            Assert.IsTrue(actual);
        }

        [Test]
        public void IsMatching_GenericMethodWithDifferentNumberOfParams_ReturnFalse()
        {
            var method1 = new MethodSignature("dll", "dummyProject", "Class1", "method2<T,Z>", new string[] { });
            var method2 = new MethodSignature("dll", "dummyProject", "Class1", "method2<1>", new string[] { });

            var actual = MethodMatcher.IsMatching(method1, method2);
            Assert.IsFalse(actual);
        }

        [Test]
        public void IsMatching_GenericMethodAndRegularMethodwithdifferentName_ReturnsFalse()
        {
            var method1 = new MethodSignature("dll", "dummyProject", "Class1", "method2<T>", new string[] { });
            var method2 = new MethodSignature("dll", "dummyProject", "Class1", "other", new string[] { });

            var actual = MethodMatcher.IsMatching(method1, method2);
            Assert.IsFalse(actual);

            actual = MethodMatcher.IsMatching(method2,method1);
            Assert.IsFalse(actual);
        }

        [Test]
        public void IsMatching_GenericMethodAndRegularMethodSameName_ReturnsFalse()
        {
            var method1 = new MethodSignature("dll", "dummyProject", "Class1", "method2<T>", new string[] { });
            var method2 = new MethodSignature("dll", "dummyProject", "Class1", "method2", new string[] { });

            var actual = MethodMatcher.IsMatching(method1, method2);
            Assert.IsFalse(actual);

            actual = MethodMatcher.IsMatching(method2, method1);
            Assert.IsFalse(actual);
        }

        [Test]
        public void IsMatching_GenericMethodWithDifferentNameSameNumArgs_ReturnsFalse()
        {
            var method1 = new MethodSignature("dll", "dummyProject", "Class1", "method2<T>", new string[] { });
            var method2 = new MethodSignature("dll", "dummyProject", "Class1", "other<1>", new string[] { });

            var actual = MethodMatcher.IsMatching(method1, method2);
            Assert.IsFalse(actual);

            actual = MethodMatcher.IsMatching(method2, method1);
            Assert.IsFalse(actual);
        }
    }
}
